﻿Imports System.Runtime.CompilerServices

Namespace Xhtml
    Public Module TextAreaExtensions

        ' These values are similar to the defaults used by WebForms
        ' when using <asp:TextBox TextMode="MultiLine"> without specifying
        ' the Rows and Columns attributes.
        Private Const TextAreaRows As Integer = 2
        Private Const TextAreaColumns As Integer = 20

        <Extension()> _
        Public Function TextArea(ByVal xHelper As XhtmlHelper, ByVal name As String) As XElement
            ' htmlAttributes 
            Return TextArea(xHelper, name, Nothing)
        End Function

        <Extension()> _
        Public Function TextArea(ByVal xHelper As XhtmlHelper, ByVal name As String, ByVal value As String) As XElement
            ' htmlAttributes 
            Return TextArea(xHelper, name, value, Nothing)
        End Function

        <Extension()> _
        Public Function TextArea(ByVal xHelper As XhtmlHelper, ByVal name As String, ByVal value As String, ByVal htmlAttributes As Object) As XElement
            Return TextArea(xHelper, name, value, New RouteValueDictionary(htmlAttributes))
        End Function

        <Extension()> _
        Public Function TextArea(ByVal xHelper As XhtmlHelper, ByVal name As String, ByVal value As String, ByVal htmlAttributes As IDictionary(Of String, Object)) As XElement
            ' Add implicit parameters
            Dim implicitAttributes As New Dictionary(Of String, Object)()
            implicitAttributes.Add("rows", TextAreaRows.ToString)
            implicitAttributes.Add("cols", TextAreaColumns.ToString)
            ' useViewData 
            ' explicitParameters 
            Return TextAreaHelper(xHelper, name, (value Is Nothing), value, implicitAttributes, Nothing, htmlAttributes)
        End Function

        <Extension()> _
        Public Function TextArea(ByVal xHelper As XhtmlHelper, ByVal name As String, ByVal value As String, ByVal rows As Integer, ByVal columns As Integer, ByVal htmlAttributes As Object) As XElement
            Return TextArea(xHelper, name, value, rows, columns, New RouteValueDictionary(htmlAttributes))
        End Function

        <Extension()> _
        Public Function TextArea(ByVal xHelper As XhtmlHelper, ByVal name As String, ByVal value As String, ByVal rows As Integer, ByVal columns As Integer, ByVal htmlAttributes As IDictionary(Of String, Object)) As XElement
            If rows <= 0 Then
                Throw New ArgumentOutOfRangeException("rows", "The value must be greater than or equal to zero.")
            End If
            If columns <= 0 Then
                Throw New ArgumentOutOfRangeException("columns", "The value must be greater than or equal to zero.")
            End If

            Dim explicitParameters As New Dictionary(Of String, Object)()
            explicitParameters.Add("rows", rows.ToString)
            explicitParameters.Add("cols", columns.ToString)
            ' useViewData 
            ' implictAttributes 
            Return TextAreaHelper(xHelper, name, (value Is Nothing), value, Nothing, explicitParameters, htmlAttributes)
        End Function

        Private Function TextAreaHelper(ByVal xHelper As XhtmlHelper, ByVal name As String, _
                                        ByVal useViewData As Boolean, ByVal value As String, _
                                        ByVal implicitAttributes As IDictionary(Of String, Object), _
                                        ByVal explicitParameters As IDictionary(Of String, Object), _
                                        ByVal htmlAttributes As IDictionary(Of String, Object)) As XElement
            If String.IsNullOrEmpty(name) Then
                Throw New ArgumentException("Value cannot be null or empty.", "name")
            End If

            Dim result = <textarea name=<%= name %>>
                             <%= value %>
                         </textarea>

            ' Add implicit attributes.
            If implicitAttributes IsNot Nothing Then
                For Each attr In implicitAttributes
                    result.SetAttributeValue(attr.Key, attr.Value)
                Next
            End If
            ' Merge htmlAttributes.
            If htmlAttributes IsNot Nothing Then
                For Each attr In htmlAttributes
                    result.SetAttributeValue(attr.Key, attr.Value)
                Next
            End If
            ' Override all the attributes with explicit parameters.
            If explicitParameters IsNot Nothing Then
                For Each attr In explicitParameters
                    result.SetAttributeValue(attr.Key, attr.Value)
                Next
            End If

            ' If there are any errors for a named field, we add the css attribute.
            Dim modelValue As ModelState = Nothing
            If xHelper.ViewData.ModelState.TryGetValue(name, modelValue) Then
                If value Is Nothing Then
                    result.SetAttributeValue("value", modelValue.Value.AttemptedValue)
                End If
                If modelValue.Errors.Count > 0 Then
                    result.SetAttributeValue("class", "input-validation-error")
                End If
            End If

            Return result
        End Function

    End Module
End Namespace